-- GroupPurchaseM
-- Create by panyl
-- 团购功能

module("GroupPurchaseM", package.seeall);

local BASE_USER_AMOUNT = 10000;

-- 所有团购商品信息
local groupPurchaseConfig = {};

-- 当前进度
local purchaseProgress = {};

-- 商城血拼回调
local whenBuyMarketGoods;

-- 载入配置表
local _init = false;
local loadCsv = function()
    if _init then return end
    _init = true;

    -- 转换下group_purchase信息表
    local group_purchase_CSV = get_group_purchase_CSV();
    for i = 1, #group_purchase_CSV do
        local goodsId = group_purchase_CSV[i].goods_id;

        groupPurchaseConfig[goodsId] = group_purchase_CSV[i];
    end
    group_purchase_CSV = {};
end

-- 模块初始化
function init()
    loadCsv();

    -- 关注获得物品的事件
    EventMgr.removeAll("GroupPurchaseM");
    EventMgr.register("GroupPurchaseM", event.BUY_GOODS, whenBuyMarketGoods);
end

-- 检索信息
function query(goodsId, path)
    local m = groupPurchaseConfig[goodsId];
    if not m or path == "" or not path then
        return m;
    else
        return m[path];
    end
end

-- 更新进度
function updateProgress(progress)
    purchaseProgress = progress;

    -- 抛出事件
    EventMgr.fire(event.UPDATE_PURCHASE_PROGRESS);
end

-- 获取团购进度
function fetchProgress(goodsId)
    if goodsId then
        return purchaseProgress[goodsId];
    end

    return purchaseProgress;
end

-- 达到某级奖励还需要的团购进度
function getLeftProgress(goodsId, level)
    local progress = fetchProgress(goodsId) or {};
    local count = progress["progress"] or 0;        -- 全服总参加人数

    local requireProgress = getRequire(goodsId, level);
    local data = ME.user.dbase:query("group_purchase", {});
    if not data or not data[goodsId] then
        -- 根本就没有参加过直接是requireProgress
        if requireProgress >= count then
            return requireProgress - count;
        else
            return 0;
        end
    end

    local tookLevel = data[goodsId]["took"] or 0;

    -- 如果已经领取过
    if tookLevel >= level then
        return 0;
    end

    -- 如果已经可以领取该等级的奖励
    if maxBonusLevel(goodsId) >= level then
        return 0;
    end

    -- 距离该奖励等级的进度
    return iif(requireProgress > count, requireProgress - count, 0);
end

-- 计算某个等级所需要的团购进度
function getRequire(goodsId, level)
    local info = purchaseProgress[goodsId] or {};

    local defaultProgress = query(goodsId, "bonus_progress") or {}; -- 配置表中的
    local customProgress = info["bonus_progress"] or {};            -- GD功能设置的，以此为优先

    -- 如果有自定义的，以此为准
    if customProgress[level] then
        return customProgress[level];
    end

    if not defaultProgress[level] then
        return 0;
    end

    return math.modf(defaultProgress[level] * BASE_USER_AMOUNT / 100);
end

-- 已经领取过的次数
function hasTookLevel(goodsId)
    local data = ME.user.dbase:query("group_purchase", {});

    if not data[goodsId] then
        return 0;
    end

    return data[goodsId]["took"] or 0;
end

-- 最高可领取的奖励等级
function maxBonusLevel(goodsId)
    -- 服务器团购人数进度
    local progress = fetchProgress(goodsId);
    if not progress then
        return 0;
    end

    -- 玩家是否参与团购了
    local data = ME.user.dbase:query("group_purchase", {});
    if not data[goodsId] then
        return 0;
    end

    return calcBonusLevel(goodsId, progress["progress"]);
end

-- 团购奖励
function calcBonus(goodsId, level)
    local formula = query(goodsId, "bonus_formula");

    if type(formula) ~= "string" then
        return {};
    end

    -- 公式计算
    return FormulaM.invoke(formula, goodsId, level);
end

-- 计算可以领取到的奖励等级
function calcBonusLevel(goodsId, count)
    if not groupPurchaseConfig[goodsId] then
        -- 没有团购信息
        return 0;
    end

    -- 如果当前进度为0
    if not purchaseProgress[goodsId] then
        return 0;
    end

    -- 默认的（配置表）
    local defaultProgress = query(goodsId, "bonus_progress") or {};
    local customProgress = purchaseProgress[goodsId]["bonus_progress"] or {};
    local max = query(goodsId, "max_times");

    for level = 1, max do
        local progress = math.modf(defaultProgress[level] * BASE_USER_AMOUNT / 100);

        -- 如果有自定义的数据，则以这个优先
        if customProgress[level] then
            progress = customProgress[level];
        end

        if not progress then
            -- 没有后面等级的奖励了
            return level - 1;
        end

        if progress > count then
            return level - 1;
        end
    end

    return max;
end

-- 能否领取团购奖励
function canTakeBonus(goodsId, level)
    local data = ME.user.dbase:query("group_purchase", {});
    if not data or not data[goodsId] then
        -- 根本就没有参加过团购
        return false;
    end

    -- 已经领取过的等级
    local tookLevel = data[goodsId]["took"] or 0;

    -- 只能一级一级领
    if tookLevel + 1 ~= level then
        return false;
    end

    -- 可以领取到的等级
    return maxBonusLevel(goodsId) >= level;
end

-- 领取团购奖励
function takeBonus(goodsId, level)
    if not canTakeBonus(goodsId, level) then
        return false;
    end

    local data = ME.user.dbase:query("group_purchase")[goodsId];

    -- 标记已领取等级
    data["took"] = level;

    local arr = calcBonus(goodsId, level);

    if #arr > 0 then
        if type(arr[1]) ~= "table" then
            arr = { arr, };
        end

        for _, bonus in pairs(arr) do
            BonusM.doBonus(bonus, "group_purchase_bonus");
        end
    end

    -- 告诉服务器
    Operation.cmd_take_group_purchase_bonus(goodsId, level);

    -- 抛出领取奖励事件
    EventMgr.fire(event.TAKE_GROUPPURCHASE_BONUS, { ["bonusList"] = arr, });
    return true;
end

-- 商城血拼回调
whenBuyMarketGoods = function(args)
    local goodsId = args.goodsId;

    if not groupPurchaseConfig[goodsId] then
        -- 不是团购类商品
        return;
    end

    -- 玩家数据
    local data = ME.user.dbase:query("group_purchase", {});

    if not data[goodsId] then
        data[goodsId] = {["count"] = 0,};
    end

    data[goodsId]["count"] = data[goodsId]["count"] + 1;
    ME.user.dbase:set("group_purchase", data);
end

-- 获得所有团购商品的id
function getGoodIsds()
    local list = {};
    for _, good in pairs(groupPurchaseConfig) do
        table.insert(list, good.goods_id);
    end
    return list;
end

-- 计算当前可领取的奖品数量
function getALlCanTakeBonusNum()
     local num = 0;
    --  (SLIMEC-3593)屏蔽团购奖励
     -- local allGoodsIds = getGoodIsds();
     -- for _, v in pairs(allGoodsIds) do
     --    local hasTakeLevel = hasTookLevel(v);
     --    local maxLevel = maxBonusLevel(v);
     --    if maxLevel - hasTakeLevel > 0 then
     --        num = num + (maxLevel - hasTakeLevel);
     --    end
     -- end

     return num;
end

-- 计算剩余领取的奖品数量
function leftBonusNum()
    local num = 0;
    local allGoodsIds = getGoodIsds();

    for _, v in pairs(allGoodsIds) do
        local hasTakeLevel = hasTookLevel(v);

        -- 下标从1开始
        local beginLevel = 1;
        if hasTakeLevel == 0 then
            beginLevel = 1;
        else
            beginLevel = hasTakeLevel
        end

        local maxLevel = query(v, "max_times");
        if maxLevel - hasTakeLevel > 0 then
            for i = beginLevel, maxLevel do
                num = num + 1;
            end
        end
    end

    return num;
end


-- 获得该物品可领取的奖励
function calcBonusAmountById(goodsId)

    local hasTakeLevel = hasTookLevel(goodsId);
    local maxLevel = maxBonusLevel(goodsId);
    return maxLevel - hasTakeLevel;
end

-- 获得未团购的冈布奥和团购了奖励没有完成的冈布奥
function getSpecialGoodsIds()
    local list = {};
    for _, good in pairs(groupPurchaseConfig) do
        local goodsId = good.goods_id;
        if hasTookLevel(good.goods_id) < query(goodsId, "max_times") then
            table.insert(list, good.goods_id);
        end
    end

    return list;
end